又碰到C的Struct

因為工作關係必須透過IPHONE跟藍牙(4.0)做溝通,並且藍芽後面還接著一顆MCU,因此就湊巧又回頭碰Struct

  1. Struct & Union
  2. Pragma pack
  3. 結構初始化
  4. Union 認識

其他相關網站

Struct & Union

取自:史丹利部落格

為了解決從MCU透過藍牙傳遞過來的資料

遇到封包裡不同的OPCODE

採取的封包解析也相對應不同

Struct & Union
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct structA {
int a;
char b;
};

struct structB {
char a;
short b;
};

struct structC {
int a;
char b;
float c;
}

struct CommuPacket {
int iPacketType;  //報文類型標誌
union {      //每次傳送的是三種報文中的一種,使用union
struct structA packetA;
struct structB packetB;
struct structC packetC;
};
};

switch(recvCommuPacket.iPacketType) {
case PACKET_A:
//A類報文處理
break;
case PACKET_B:
…  //B類報文處理
break;
case PACKET_C:
//C類報文處理
break;
}

pragma pack(n)

同樣取自:史丹利部落格

自然對界

  struct是一種複合資料類型,其構成元素既可以是基本資料類型(如int、long、float等)的變數,也可以是一些複合資料類型(如array、struct、union等)的資料單元。對於結構體,編譯器會自動進行成員變數的對齊,以提高運算效率。缺省情況下,編譯器為結構體的每個成員按其自然對界(natural alignment)條件分配空間。各個成員按照它們被聲明的順序在記憶體中順序存儲,第一個成員的位址和整個結構的位址相同。

  自然對界(natural alignment)即默認對齊方式,是指按結構體的成員中size最大的成員對齊。

指定對界

一般地,可以通過下面的方法來改變缺省的對界條件:

  • 使用虛擬指令#pragma pack(n),編譯器將按照n個位元組對齊;
  • 使用虛擬指令#pragma pack(),取消自定義位元組對齊方式。

  注意:如果#pragma pack (n)中指定的n大於結構體中最大成員的size,則其不起作用,結構體仍然按照size最大的成員進行對界。

pragma pack(n)
1
2
3
4
5
6
7
#pragma pack(n)
struct naturalalign {
char a;
int b;
char c;
};
//當n為4、8、16時,其對齊方式均一樣,sizeof(naturalalign)的結果都等於12。而當n為2時,其發揮了作用,使得sizeof(naturalalign)的結果為8。

結構初始化

C的結構是能夠在初始化時,個別給值滴

在這篇有提到,該如何個別給值

C: Structure Initialization (Advanced)

Structure Initialization (Advanced)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct student {

int roll;

int class;

char name[50];

};

//以前我的寫法
student st3={1038,10,"Mark"};

//他的範例
student st3={

.name = "Mark", //Notice the equal to and the comma

.class = 10,

.roll = 1038

};

:

接著是『』,映象中以前沒用過:

Structures Nested Inside Unions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef union
{
struct
{
uint8_t a:1;
uint8_t b:1;
uint8_t c:1;
uint8_t d:1;

uint8_t e:1;
uint8_t f:1;
uint8_t g:1;
uint8_t h:1;
} items;
uint8_t yy;
uint8_t zz;
} typeName_t;

typeName_t t;
// hgfe dcba
t.yy = 0xc0; // 0b 1100 0000

t.items.a = 1; // 0b 1100 0001

t.items.c = 1; // 0b 1100 0101

t.items.g = 0; // 0b 1000 0101

Union 認識

另外是對union有多一點的認識

Union 練習
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma pack(1)
typedef struct parameter{
uint8_t deviceID;
uint8_t versionPre;
uint8_t versionSuffix;
uint8_t dataType;
}parameter;

#pragma pack(1)
typedef struct setting{
uint8_t deviceID;
uint8_t versionPre;
uint8_t versionSuffix;
uint8_t dataType;
uint8_t dataType1;
uint8_t dataType2;
}setting;

#pragma pack(1)
typedef struct{
int32_t len;

union {
setting s;
parameter p;
};

union{
uint8_t secret;
int digest;
};
}fileData;

parameter p = {1,2,3,4};
setting s = {5,6,7,8,9,10};

fileData f1 = {1,.p=p,.secret=11}; // [1,[1,2,3,4,0,0],[11]]

fileData f2 = {2,.s=s,.secret=12}; // [2,[5,6,7,8,9,10],[12]]